﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Security.Permissions;
using System.Text;

namespace Extented.UI.Core.Helpers
{
    public static class SecurityHelper
    {
        static bool forcePartialTrustMode;
        public static bool IsPartialTrust
        {
            get
            {
                return forcePartialTrustMode || !IsPermissionGranted(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess));
            }
        }
        public static bool ForcePartialTrustMode { get { return forcePartialTrustMode; } set { forcePartialTrustMode = value; } }
        public static bool IsWeakRefAvailable
        {
            get { return IsPermissionGranted(new WeakReferencePermission()); }
        }
#if !DXWINDOW
        public static bool IsUnmanagedCodeGrantedAndHasZeroHwnd
        {
            get { return SecurityHelper.IsPermissionGranted(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)) && GraphicsHelper.CanCreateFromZeroHwnd; }
        }
        public static bool IsUnmanagedCodeGrantedAndCanUseGetHdc
        {
            get { return SecurityHelper.IsPermissionGranted(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)) && GraphicsHelper.CanUseGetHdc; }
        }
#endif
        [ThreadStatic]
        static PermissionCheckerSet permissionCheckerSet;
        public static bool IsPermissionGranted(IPermission permission)
        {
            if (permissionCheckerSet == null)
                permissionCheckerSet = new PermissionCheckerSet();
            return permissionCheckerSet.IsGranted(permission);
        }
        public static void ForceRecheckPermissions()
        {
            permissionCheckerSet = null;
        }
    }

    class WeakReferencePermission : IPermission
    {
        #region IPermission Members
        public IPermission Copy()
        {
            throw new NotImplementedException();
        }
        public void Demand()
        {
            new WeakReference(new object());
        }
        public IPermission Intersect(IPermission target)
        {
            throw new NotImplementedException();
        }
        public bool IsSubsetOf(IPermission target)
        {
            return target is WeakReferencePermission;
        }
        public IPermission Union(IPermission target)
        {
            throw new NotImplementedException();
        }
        #endregion
        #region ISecurityEncodable Members
        public void FromXml(SecurityElement e)
        {
            throw new NotImplementedException();
        }
        public SecurityElement ToXml()
        {
            throw new NotImplementedException();
        }
        #endregion
    }

    public class PermissionChecker
    {
        bool? isPermissionGranted;
        IPermission permission;
        public IPermission Permission
        {
            get { return permission; }
        }
        public bool IsPermissionGranted
        {
            get
            {
                if (!isPermissionGranted.HasValue)
                    isPermissionGranted = IsPermissionGrantedCore(permission);
                return isPermissionGranted.Value;
            }
        }
        public PermissionChecker(IPermission permission)
        {
            this.permission = permission;
        }
        bool IsPermissionGrantedCore(IPermission permission)
        {
            try
            {
                permission.Demand();
                return true;
            }
            catch (SecurityException)
            {
                return false;
            }
        }
    }

    class PermissionCheckerSet
    {
        List<PermissionChecker> checkers = new List<PermissionChecker>();
        public bool IsGranted(IPermission permission)
        {
            PermissionChecker checker = GetChecker(permission);
            if (checker == null)
            {
                checker = new PermissionChecker(permission);
                checkers.Add(checker);
            }
            return checker.IsPermissionGranted;
        }
        PermissionChecker GetChecker(IPermission permission)
        {
            foreach (PermissionChecker checker in checkers)
            {
                if (checker.Permission.GetType() == permission.GetType() && permission.IsSubsetOf(checker.Permission))
                    return checker;
            }
            return null;
        }
    }
}
